package com.fsu.database.dao;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

/**
 * Singleton Data Access Object (DAO) for Users. This class should never be
 * used explicitly, but interfaced through the DatabaseManager 
 * class, instead.
 * @author Bonazza
 *
 */
public class UserDAO {
	/**
	 * Singleton instance object
	 */
	private static UserDAO instance;
	/**
	 * SQL Database connection object
	 */
	private Connection con;
	
	/**
	 * Constructor
	 * @param c
	 */
	private UserDAO(Connection c) {
		con = c;
	}
	
	/**
	 * Retrieve the singleton UserDAO instance
	 * @param c a database Connection object
	 * @return The singleton instance of the UserDAO
	 */
	public static synchronized UserDAO getInstance(Connection c) {
		if(instance == null)
			instance = new UserDAO(c);
		
		return instance;
	}
	
	/**
	 * Checks whether a specified user exists or not
	 * @param login the user's username
	 * @return
	 * @throws SQLException
	 */
	public boolean userExists(String login) throws SQLException {
		final String q = "SELECT Login FROM Users WHERE Login=?";
		
		PreparedStatement pstmt = con.prepareStatement(q);
		pstmt.clearParameters();
		pstmt.setString(1, login);
		ResultSet cursor = pstmt.executeQuery();
		
		return cursor.next();
	}
	
	/**
	 * Adds a specified user to the database. If the 
	 * user already exists, nothing is done
	 * @param user The user to be added
	 * @throws SQLException
	 */
	public void addUser(User user) throws SQLException {
		
		if(userExists(user.getUsername())) return;
		
		final String q = "INSERT INTO Users VALUES(?, ?, ?, ?, ?, ?, ?)";
		final int isAdmin = user.isAdmin() ? 1 : 0;
		
		PreparedStatement pstmt = con.prepareStatement(q);
		pstmt.setString(1, user.getUsername());
		pstmt.setString(2, user.getPassword());
		pstmt.setString(3, user.getName());
		pstmt.setString(4, user.getEmail());
		pstmt.setString(5, user.getAddress());
		pstmt.setString(6, user.getPhone());
		pstmt.setInt(7, isAdmin);
		
		pstmt.executeUpdate();
	}
	
	/**
	 * Updates the information for a registered user
	 * @param oldUser the old information for the user (we only
	 * really care about the username, so that is technically
	 * all that is needed)
	 * @param newUser the new information for the user. This user 
	 * object must be completely populated with valid data.
	 * @throws SQLException
	 */
	public void updateUser(User oldUser, User newUser) throws SQLException {
		
		final String q = "UPDATE Users " +
				"SET Login=?, Password=?, Name=?, Email=?, Address=?, Phone#=?, is_admin=? " +
				"WHERE Login=?";
		final int isAdmin = newUser.isAdmin() ? 1 : 0;
		
		PreparedStatement pstmt = con.prepareStatement(q);
		pstmt.setString(1, newUser.getUsername());
		pstmt.setString(2, newUser.getPassword());
		pstmt.setString(3, newUser.getName());
		pstmt.setString(4, newUser.getEmail());
		pstmt.setString(5, newUser.getAddress());
		pstmt.setString(6, newUser.getPhone());
		pstmt.setInt(7, isAdmin);
		pstmt.setString(8, oldUser.getUsername());
		
		pstmt.executeUpdate();
	}
	
	/**
	 * Retrieves the information for a specified user
	 * @param login the username of the user to retrieve
	 * @return A User object containing the information for the
	 * specified user
	 * @throws SQLException
	 */
	public User getUser(String login) throws SQLException {
		final String q = "SELECT u.Login, u.Password, u.Name, u.Email, u.Address, u.Phone#, u.is_admin FROM Users u WHERE u.Login = '" + login + "'";
		User user = null;
		System.out.println(q);
		Statement stmt = con.createStatement();
		ResultSet cursor = stmt.executeQuery(q);
		
		if(cursor.next()) {
			String username = cursor.getString(1);
			String password = cursor.getString(2);
			String name = cursor.getString(3);
			String email = cursor.getString(4);
			String addy = cursor.getString(5);
			String phone = cursor.getString(6);
			int isAdmin = cursor.getInt(7);
			
			user = new User(username, 
					password, 
					name, 
					email,
					addy,
					phone,
					isAdmin == 1 ? true : false);
			
		}
		
		return user;
	}
}
